#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/gpio/driver.h>
#include <linux/mutex.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/interrupt.h>
#include <linux/debugfs.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/atomic.h>
#include <linux/kthread.h>
#include <generated/uapi/linux/version.h>

#define DEVICE_NAME "etek,et6416"
#define ET6416_BANK_NUM 16

#define ET6416_DEBUG_CONFIG         1
#define ET6416_ENABLE_IRQ           0
#define ET6416_ENABLE_DEBUGFS       1
#define KERNEL_VERSION_OVER_6_0_1   0

#if ET6416_DEBUG_CONFIG
#define et6416_err(dev, fmt, ...)    \
    dev_err(dev, "%s:%d:" fmt, __func__, __LINE__, ##__VA_ARGS__)
#else
#define et6416_err(dev, fmt, ...)
#endif

typedef enum ET6416_REG {
    INPUT_REG_0 = 0x00,
    INPUT_REG_1,
    OUTPUT_REG_0,
    OUTPUT_REG_1,
    POLARITY_REG_0,
    POLARITY_REG_1,
    CONFIG_REG_0,
    CONFIG_REG_1,
} REG;

static bool gpio_register_status[ET6416_BANK_NUM] = {false};

typedef struct et6416_gpio_control {
    struct gpio_chip chip;
    int base;
    unsigned int bank;   //一个gpio控制器有几组pins
} ET6416_gc;

typedef struct et6416_platform_data {
    const char *name;
    struct device *dev;
    struct gpio_desc *gpio_irq_desc;
    struct regmap *et6416_regmap;
    struct i2c_client *client;
#if ET6416_ENABLE_DEBUGFS
    struct dentry *et6416_dir;
    struct dentry *et6416_file;
#endif
    const char *const *str_name;
    struct mutex i2c_lock;
    struct mutex request_gpio_lock;
    ET6416_gc gc;
    int gpio_reset;
#if ET6416_ENABLE_IRQ
    int gpio_irq;
    int irq_num;
    wait_queue_head_t et6416_wait_queue;
    struct task_struct *et6416_thread;
    atomic_t irq_event;
    unsigned int input_reg_0_value;
    unsigned int input_reg_1_value;
    unsigned int new_input_reg_0_value;
    unsigned int new_input_reg_1_value;
#endif
    int addr;
} ET6416_data;

static const struct regmap_config et6416_config = {
    .reg_bits = 8,
    .val_bits = 8,
    .max_register = CONFIG_REG_1,
};

static const char *gpio_desc_name[ET6416_BANK_NUM] = { NULL };

static int et6416_i2c_write(ET6416_data *et6416, REG reg, unsigned int value)
{   
    int ret = 0;

    mutex_lock(&et6416->i2c_lock);
    ret = regmap_write(et6416->et6416_regmap, reg, value);
    mutex_unlock(&et6416->i2c_lock);
    if (ret < 0) {
        et6416_err(et6416->dev, "Failed to write register\n");
        return ret;
    }

    return 0;
}

static int et6416_i2c_read(ET6416_data *et6416, REG reg, unsigned int *value)
{   
    int ret = 0;

    mutex_lock(&et6416->i2c_lock);
    ret = regmap_read(et6416->et6416_regmap, reg, value);
    mutex_unlock(&et6416->i2c_lock);
    if (ret < 0) {
        et6416_err(et6416->dev, "Failed to read register\n");
        return ret;
    }

    return 0;
}

static int et6416_i2c_update_bits(ET6416_data *et6416, REG reg,
                                    unsigned int mask, unsigned int value)
{   
    int ret = 0;

    mutex_lock(&et6416->i2c_lock);
    ret = regmap_update_bits(et6416->et6416_regmap, reg, mask, value);
    mutex_unlock(&et6416->i2c_lock);
    if (ret < 0) {
        et6416_err(et6416->dev, "Failed to update bits register\n");
        return ret;
    }

    return 0;
}

static int et6416_gpio_request(struct gpio_chip *gc,
						unsigned int offset)
{
    ET6416_data *et6416 = container_of(gc, ET6416_data, gc.chip);

    if (!et6416) {
        et6416_err(et6416->dev, "et6416 is null return\n");
        return -ENOMEM;
    }

    if ((offset > ET6416_BANK_NUM) || (offset < 0)) {
        et6416_err(et6416->dev, "offset is error\n");
        return -EINVAL;
    }
    mutex_lock(&et6416->request_gpio_lock);
    if (gpio_register_status[offset]) {
        et6416_err(et6416->dev, "%s has been registered \n", gc->names[offset]);
        mutex_unlock(&et6416->request_gpio_lock);
        return -EINVAL;
    }

    gpio_register_status[offset] = true;

    mutex_unlock(&et6416->request_gpio_lock);

    et6416_err(et6416->dev, "successful\n");
    return 0;
}

static void et6416_gpio_free(struct gpio_chip *gc,
						unsigned int offset)
{
    ET6416_data *et6416 = container_of(gc, ET6416_data, gc.chip);

    if (!et6416) {
        et6416_err(et6416->dev, "et6416 is null return\n");
        return;
    }

    if ((offset > ET6416_BANK_NUM) || (offset < 0)) {
        et6416_err(et6416->dev, "offset is error\n");
        return;
    }
    mutex_lock(&et6416->request_gpio_lock);
    if (!gpio_register_status[offset]) {
        et6416_err(et6416->dev, "%s has not been registered \n", gc->names[offset]);
        mutex_unlock(&et6416->request_gpio_lock);
        return;
    }

    gpio_register_status[offset] = false;

    mutex_unlock(&et6416->request_gpio_lock);

    et6416_err(et6416->dev, "successful\n");
}

static int et6416_gpio_get_direction(struct gpio_chip *gc,
						unsigned int offset)
{
    ET6416_data *et6416 = container_of(gc, ET6416_data, gc.chip);
    bool is_io1 = false;
    unsigned int value;
    int ret = 0;

    if (!et6416) {
        et6416_err(et6416->dev, "et6416 is null return\n");
        goto err;
    }
    mutex_lock(&et6416->request_gpio_lock);
    if (!gpio_register_status[offset]) {
        et6416_err(et6416->dev, "%s has not been registered \n", gc->names[offset]);
        mutex_unlock(&et6416->request_gpio_lock);
        goto err;
    }
    mutex_unlock(&et6416->request_gpio_lock);

    is_io1 = (offset >= 0x8) ? true : false;
    if (is_io1) {
        ret = et6416_i2c_read(et6416, CONFIG_REG_1, &value);
        if (ret) {
            et6416_err(et6416->dev, "et6416_i2c_read fail\n");
            goto err;
        }
        value &= (0x1 << (offset - 0x8));
        value >>= (offset - 0x8);
    } else {
        ret = et6416_i2c_read(et6416, CONFIG_REG_0, &value);
        if (ret) {
            et6416_err(et6416->dev, "et6416_i2c_read fail\n");
            goto err;
        }
        value &= (0x1 << offset);
        value >>= offset;       
    }
    
    et6416_err(et6416->dev, "successful\n");
    return !!value;

err:
    et6416_err(et6416->dev, "fail\n");
    return -1;
}

static int et6416_gpio_direction_input(struct gpio_chip *gc,
						unsigned int offset)
{
    ET6416_data *et6416 = container_of(gc, ET6416_data, gc.chip);
    bool is_io1 = false;
    int ret = 0;

    if (!et6416) {
        et6416_err(et6416->dev, "et6416 is null return\n");
        return -ENOMEM;
    }

    mutex_lock(&et6416->request_gpio_lock);
    if (!gpio_register_status[offset]) {
        et6416_err(et6416->dev, "%s has not been registered \n", gc->names[offset]);
        mutex_unlock(&et6416->request_gpio_lock);
        return -EINVAL;
    }
    mutex_unlock(&et6416->request_gpio_lock);

    is_io1 = (offset >= 0x8) ? true : false;
    if (is_io1) {
        ret = et6416_i2c_update_bits(et6416, CONFIG_REG_1, (0x1 << (offset - 0x8)), 1);
        if (ret) {
            et6416_err(et6416->dev, "et6416_i2c_update_bits fail\n");
            goto err;
        }
    } else {
        ret = et6416_i2c_update_bits(et6416, CONFIG_REG_0, (0x1 << offset), 1);
        if (ret) {
            et6416_err(et6416->dev, "et6416_i2c_update_bits fail\n");
            goto err;
        }    
    }

    et6416_err(et6416->dev, "successful\n");
    return 0;
err:
    et6416_err(et6416->dev, "fail\n");
    return -1;  
}

static int et6416_gpio_direction_output(struct gpio_chip *gc,
						unsigned int offset, int value)
{
    ET6416_data *et6416 = container_of(gc, ET6416_data, gc.chip);
    bool is_io1 = false;
    int ret = 0;

    if (!et6416) {
        et6416_err(et6416->dev, "et6416 is null return\n");
        return -ENOMEM;
    }
    mutex_lock(&et6416->request_gpio_lock);
    if (!gpio_register_status[offset]) {
        et6416_err(et6416->dev, "%s has not been registered \n", gc->names[offset]);
        mutex_unlock(&et6416->request_gpio_lock);
        return -EINVAL;
    }
    mutex_unlock(&et6416->request_gpio_lock);

    if ((value != 1) && (value != 0)) {
        et6416_err(et6416->dev, "value is err value\n");
        goto err;
    }

    is_io1 = (offset >= 0x8) ? true : false;
    if (is_io1) {
        //设置成输出模式
        ret = et6416_i2c_update_bits(et6416, CONFIG_REG_1, (0x1 << (offset - 0x8)), 0);
        if (ret) {
            et6416_err(et6416->dev, "et6416_i2c_update_bits fail\n");
            goto err;
        }
        //设置输出值
        ret = et6416_i2c_update_bits(et6416, OUTPUT_REG_1, (0x1 << (offset - 0x8)), value);
        if (ret) {
            et6416_err(et6416->dev, "et6416_i2c_update_bits fail\n");
            goto err;
        }
    } else {
        ret = et6416_i2c_update_bits(et6416, CONFIG_REG_0, (0x1 << offset), 0);
        if (ret) {
            et6416_err(et6416->dev, "et6416_i2c_update_bits fail\n");
            goto err;
        }   
        ret = et6416_i2c_update_bits(et6416, OUTPUT_REG_0, (0x1 << offset), value);
        if (ret) {
            et6416_err(et6416->dev, "et6416_i2c_update_bits fail\n");
            goto err;
        }  
    }

    et6416_err(et6416->dev, "successful\n");
    return 0;
err:
    et6416_err(et6416->dev, "fail\n");
    return -1;
}

static int et6416_gpio_get_value(struct gpio_chip *gc, unsigned int offset)
{
    ET6416_data *et6416 = container_of(gc, ET6416_data, gc.chip);
    bool is_io1 = false;
    int ret = 0;
    bool input;
    unsigned int value;

    if (!et6416) {
        et6416_err(et6416->dev, "et6416 is null return\n");
        return -ENOMEM;
    }
    mutex_lock(&et6416->request_gpio_lock);
    if (!gpio_register_status[offset]) {
        et6416_err(et6416->dev, "%s has not been registered \n", gc->names[offset]);
        mutex_unlock(&et6416->request_gpio_lock);
        return -EINVAL;
    }
    mutex_unlock(&et6416->request_gpio_lock);

    is_io1 = (offset >= 0x8) ? true : false;
    input = et6416_gpio_get_direction(gc, offset);
    if (is_io1) {
        ret = et6416_i2c_read(et6416, (input ? INPUT_REG_1 : OUTPUT_REG_1), &value);
        if (ret) {
            et6416_err(et6416->dev, "et6416_i2c_read fail\n");
            goto err;
        }
        value &= (0x1 << (offset - 0x8));
        value >>= (offset - 0x8);  
    } else {
        ret = et6416_i2c_read(et6416, (input ? INPUT_REG_0 : OUTPUT_REG_0), &value);
        if (ret) {
            et6416_err(et6416->dev, "et6416_i2c_read fail\n");
            goto err;
        }
        value &= (0x1 << offset);
        value >>= offset;        
    }

    et6416_err(et6416->dev, "successful\n");
    return !!value;

err:
    et6416_err(et6416->dev, "fail\n");
    return -1;
}

static void et6416_gpio_set_value(struct gpio_chip *gc, unsigned int offset, int value)
{
    ET6416_data *et6416 = container_of(gc, ET6416_data, gc.chip);
    bool is_io1 = false;
    int ret = 0;

    if (!et6416) {
        et6416_err(et6416->dev, "et6416 is null return\n");
        return;
    }
    mutex_lock(&et6416->request_gpio_lock);
    if (!gpio_register_status[offset]) {
        et6416_err(et6416->dev, "%s has not been registered \n", gc->names[offset]);
        mutex_unlock(&et6416->request_gpio_lock);
        return;
    }
    mutex_unlock(&et6416->request_gpio_lock);

    if ((value != 1) && (value != 0)) {
        et6416_err(et6416->dev, "value is err value\n");
        goto err;
    }

    is_io1 = (offset >= 0x8) ? true : false;
    if (is_io1) {
        //设置成输出模式
        ret = et6416_i2c_update_bits(et6416, CONFIG_REG_1, (0x1 << (offset - 0x8)), 0);
        if (ret) {
            et6416_err(et6416->dev, "et6416_i2c_update_bits fail\n");
            goto err;
        }
        //设置输出值
        ret = et6416_i2c_update_bits(et6416, OUTPUT_REG_1, (0x1 << (offset - 0x8)), value);
        if (ret) {
            et6416_err(et6416->dev, "et6416_i2c_update_bits fail\n");
            goto err;
        }
    } else {
        ret = et6416_i2c_update_bits(et6416, CONFIG_REG_0, (0x1 << offset), 0);
        if (ret) {
            et6416_err(et6416->dev, "et6416_i2c_update_bits fail\n");
            goto err;
        }   
        ret = et6416_i2c_update_bits(et6416, OUTPUT_REG_0, (0x1 << offset), value);
        if (ret) {
            et6416_err(et6416->dev, "et6416_i2c_update_bits fail\n");
            goto err;
        }  
    }
    et6416_err(et6416->dev, "successful\n");
    return;
err:
    et6416_err(et6416->dev, "fail\n");
    return;
}

static void et6416_gpiochip_init_set(ET6416_data *et6416)
{
    struct gpio_chip *chip = &et6416->gc.chip;

    chip->label = DEVICE_NAME;
    chip->owner = THIS_MODULE;
    chip->request = et6416_gpio_request;
    chip->free = et6416_gpio_free;
    chip->get = et6416_gpio_get_value;
	chip->set = et6416_gpio_set_value;
    chip->get_direction = et6416_gpio_get_direction;
    chip->direction_input = et6416_gpio_direction_input;
    chip->direction_output = et6416_gpio_direction_output;
    chip->base = et6416->gc.base;
    chip->ngpio = et6416->gc.bank;
    chip->of_node = et6416->dev->of_node;
    chip->parent = &et6416->client->dev;
    chip->names = et6416->str_name;
}

static int et6416_get_of_pdata(struct device *dev, ET6416_data *et6416)
{
    int ret = 0;

#if ET6416_ENABLE_IRQ
    et6416->gpio_irq = of_get_named_gpio(dev->of_node,
                                        "et6416,gpio_intr", 0);
    if (et6416->gpio_irq < 0) {
        et6416_err(dev, "Failed to get gpio irq from device tree\n");
        return -EINVAL;
    }
#endif
    et6416->gpio_reset = of_get_named_gpio(dev->of_node,
                                        "et6416,gpio_reset", 0);
    if (et6416->gpio_reset < 0) {
        et6416_err(dev, "Failed to get gpio reset from device tree\n");
        return -EINVAL;
    }

    ret = of_property_read_u32(dev->of_node, "et6416,gpio_bank", &et6416->gc.bank);
    if (ret) {
        et6416_err(et6416->dev, "Failed to read my_property\n");
        return ret;
    }

    ret = of_property_read_string_array(dev->of_node, "et6416,gpio_names", gpio_desc_name, ET6416_BANK_NUM);
    if (ret != ET6416_BANK_NUM) {
        et6416_err(dev, "Failed to read my_strings property\n");
        return ret;
    }

    return 0;
}
#if ET6416_ENABLE_IRQ
static int et6416_interrupt_handle(ET6416_data *et6416)
{
    unsigned char diff0 = 0, diff1 = 0;
    int ret = 0;

    ret = et6416_i2c_read(et6416, INPUT_REG_0, &et6416->new_input_reg_0_value);
    if (ret) {
        et6416_err(et6416->dev, "et6416_i2c_read fail\n");
        return -1;
    }
    ret = et6416_i2c_read(et6416, INPUT_REG_1, &et6416->new_input_reg_1_value);
    if (ret) {
        et6416_err(et6416->dev, "et6416_i2c_read fail\n");
        return -1;
    }

    diff0 = et6416->input_reg_0_value ^ et6416->new_input_reg_0_value;
    diff1 = et6416->input_reg_1_value ^ et6416->new_input_reg_1_value;

    if (!diff0 && !diff1)
        return 0;
    
    et6416_err(et6416->dev, "diff0 = 0x%x diff1 = 0x%x\n", diff0, diff1);

    return 0;
}

static int et6416_interrupt_thread(void *data)
{
    ET6416_data *et6416 = data;

    while(!kthread_should_stop()) {
        wait_event_interruptible(et6416->et6416_wait_queue, atomic_read(&et6416->irq_event));
        et6416_interrupt_handle(et6416);
        if (atomic_read(&et6416->irq_event) > 0)
            atomic_sub(1, &et6416->irq_event);
    }
    return 0;
}

static irqreturn_t et6416_irq_handler(int irq, void *arg)
{
    ET6416_data *et6416 = arg;

    //延迟抖动
    mdelay(150);
    atomic_inc(&et6416->irq_event);
    wake_up(&et6416->et6416_wait_queue);

    return IRQ_HANDLED;
}

static int et6416_interrupt_register(ET6416_data *et6416)
{
    int ret = 0;

    ret = devm_gpio_request(et6416->dev, et6416->gpio_irq, "et6416_gpio_irq");
    if (ret) {
        et6416_err(et6416->dev, "Failed to request GPIO pin %d\n", et6416->gpio_irq);
        return ret;
    }

    et6416->irq_num = gpio_to_irq(et6416->gpio_irq);
    if (et6416->irq_num < 0) {
        et6416_err(et6416->dev, "Failed to get IRQ number for GPIO pin %d\n", et6416->gpio_irq);
        return et6416->irq_num;
    }

    atomic_set(&et6416->irq_event, 0);
    init_waitqueue_head(&et6416->et6416_wait_queue);

    et6416->et6416_thread = kthread_run(et6416_interrupt_thread, et6416, "et6416_irq_thread");
    if (!et6416->et6416_thread) {
        et6416_err(et6416->dev, "Failed to create thread\n");
        return -1;
    }

    ret = devm_request_threaded_irq(et6416->dev, et6416->irq_num, NULL, et6416_irq_handler,
                    IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "et6416_irq_handler", et6416);
    if (ret) {
        et6416_err(et6416->dev, "Failed to request IRQ for GPIO pin %d\n", et6416->gpio_irq);
        return ret;
    }

    return 0;
}
#endif
static int et6416_hw_init(ET6416_data *et6416)
{
    int ret = 0;

    //默认不使用极性反转功能
    ret = et6416_i2c_write(et6416, POLARITY_REG_0, 0x00);
    if (ret) {
        et6416_err(et6416->dev, "et6416_i2c_write fail\n");
        goto err;
    }
    ret = et6416_i2c_write(et6416, POLARITY_REG_1, 0x00);
    if (ret) {
        et6416_err(et6416->dev, "et6416_i2c_write fail\n");
        goto err;
    }
    //默认全部设置成输出模式
    ret = et6416_i2c_write(et6416, CONFIG_REG_0, 0x00);
    if (ret) {
        et6416_err(et6416->dev, "et6416_i2c_write fail\n");
        goto err;
    }
    ret = et6416_i2c_write(et6416, CONFIG_REG_1, 0x00);
    if (ret) {
        et6416_err(et6416->dev, "et6416_i2c_write fail\n");
        goto err;
    }
    //全部默认输出高电平
    ret = et6416_i2c_write(et6416, OUTPUT_REG_0, 0xff);
    if (ret) {
        et6416_err(et6416->dev, "et6416_i2c_write fail\n");
        goto err;
    }
    ret = et6416_i2c_write(et6416, OUTPUT_REG_1, 0xff);
    if (ret) {
        et6416_err(et6416->dev, "et6416_i2c_write fail\n");
        goto err;
    }
#if ET6416_ENABLE_IRQ
    ret = et6416_i2c_read(et6416, INPUT_REG_0, &et6416->input_reg_0_value);
    if (ret) {
        et6416_err(et6416->dev, "et6416_i2c_read fail\n");
        goto err;
    }

    ret = et6416_i2c_read(et6416, INPUT_REG_1, &et6416->input_reg_1_value);
    if (ret) {
        et6416_err(et6416->dev, "et6416_i2c_read fail\n");
        goto err;
    }
    et6416_err(et6416->dev, "input_reg_0_value = 0x%x\n", et6416->input_reg_0_value);
    et6416_err(et6416->dev, "input_reg_1_value = 0x%x\n", et6416->input_reg_1_value);
#endif
    et6416_err(et6416->dev, "hw init successful\n");
    return ret;
err:
    et6416_err(et6416->dev, "hw init failed\n");
    return ret;
}

#if ET6416_ENABLE_DEBUGFS
static const char *const str_arr[3] = {
    "echo r:[reg_addr] > et6416_ops",
    "echo w:[reg_addr]:[reg_value] > et6416_ops",
    "echo d > et6416_ops"
};

static ssize_t et6416_debugfs_read(struct file *file, char __user *buf,
                            size_t count, loff_t *ppos)
{
    ET6416_data *et6416 = (ET6416_data *)file->private_data;

    if (!et6416) {
        et6416_err(et6416->dev, "et6416 is null\n");
        return -ENOMEM;
    }

    return count;
}

static ssize_t et6416_debugfs_write(struct file *file, const char __user *buf,
                             size_t count, loff_t *ppos)
{
    ssize_t ret;
    ET6416_data *et6416 = (ET6416_data *)file->private_data;
    unsigned char buffer[128];
    unsigned int int_buffer[2];
    char *token = NULL;
    char *str_buffer = buffer;

    if (!et6416)
        return -ENOMEM;

    if (count > sizeof(buffer) - 1) {
        et6416_err(et6416->dev, "Buffer overflow attempt\n");
        return -EINVAL;
    }

    memset(buffer, 0, sizeof(buffer));

    ret = copy_from_user(buffer, buf, count);
    if (ret) {
        et6416_err(et6416->dev, "Failed to copy data from user space\n");
        return -EFAULT;
    }

    //确保数组以'\0'结尾
    buffer[count] = '\0';
    et6416_err(et6416->dev, "Data written to debugfs: %s", buffer);

    switch(buffer[0]) {
        case 'r': {
            unsigned int value;

            token = strsep(&str_buffer, ":");
            if (token && token[0] == 'r') {
                token = strsep(&str_buffer, ":");
            }            
            ret = kstrtoint(token, 16, &int_buffer[0]);
            if (ret) {
                et6416_err(et6416->dev, "Failed to convert string to int\n");
                return -EINVAL;
            }
            et6416_err(et6416->dev, "reg_addr = 0x%x\n", int_buffer[0]);
            ret = et6416_i2c_read(et6416, int_buffer[0], &value);
            if (ret) {
                et6416_err(et6416->dev, "et6416_i2c_read fail\n");
                return -1;
            }
            et6416_err(et6416->dev, "value = 0x%x\n", value);
            break;
        }
        case 'w':
            token = strsep(&str_buffer, ":");
            if (token && token[0] == 'w') {
                token = strsep(&str_buffer, ":");
            }
            ret = kstrtoint(token, 16, &int_buffer[0]);
            if (ret) {
                et6416_err(et6416->dev, "Failed to convert string to int\n");
                return -EINVAL;
            }
            token = strsep(&str_buffer, ":");
            ret = kstrtoint(token, 16, &int_buffer[1]);
            if (ret) {
                et6416_err(et6416->dev, "Failed to convert string to int\n");
                return -EINVAL;
            }
            et6416_err(et6416->dev, "reg_addr = 0x%x\n", int_buffer[0]);
            et6416_err(et6416->dev, "value_addr = 0x%x\n", int_buffer[1]);
            ret = et6416_i2c_write(et6416, int_buffer[0], int_buffer[1]);
            if (ret) {
                et6416_err(et6416->dev, "et6416_i2c_write fail\n");
                return -1;
            }
            break;
        case 'd': {
            unsigned int value = 0;
            unsigned int i;
            for (i = 0; i <= CONFIG_REG_1; i++) {
                ret = et6416_i2c_read(et6416, i, &value);
                if (ret) {
                    et6416_err(et6416->dev, "et6416_i2c_read fail\n");
                    return -1;
                }
                et6416_err(et6416->dev, "REG[%d] = 0x%x\n", i, value); 
                value = 0;            
            }
            break;
        }
        default:
            et6416_err(et6416->dev, "format error,please input %s\n", str_arr[0]);
            et6416_err(et6416->dev, "format error,please input %s\n", str_arr[1]);
            et6416_err(et6416->dev, "format error,please input %s\n", str_arr[2]);
            break;
    }

    return count;
}

static int et6416_debugfs_open(struct inode *inode, struct file *file)
{
    file->private_data = inode->i_private;

    return 0;
}

static int et6416_debugfs_release(struct inode *inode, struct file *file)
{
    file->private_data = NULL;
    return 0;
}

static const struct file_operations et6416_fops = {
    .owner = THIS_MODULE,
    .open = et6416_debugfs_open,
    .release = et6416_debugfs_release,
    .write = et6416_debugfs_write,
    .read = et6416_debugfs_read,
};

static int et6416_create_debugfs(ET6416_data *et6416)
{
    et6416->et6416_dir = debugfs_create_dir("et6416", NULL);
    if (!et6416->et6416_dir) {
        et6416_err(et6416->dev, "debugfs create dir fail\n");
        return -ENOMEM;
    }

    et6416->et6416_file = debugfs_create_file("et6416_ops", 0444, et6416->et6416_dir, et6416, &et6416_fops);
    if (!et6416->et6416_file) {
        et6416_err(et6416->dev, "debugfs create file fail\n");
        debugfs_remove(et6416->et6416_dir);
        return -ENOMEM;
    }

    et6416_err(et6416->dev, "debugfs create successful\n");
    return 0;
}
#endif

static int et6416_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    ET6416_data *et6416 = NULL;
    int ret = 0;

    et6416 = kmalloc(sizeof(ET6416_data), GFP_KERNEL);
    if (!et6416) {
        et6416_err(&client->dev, "ET6416_data malloc fail\n");
        return -ENOMEM;
    }

    //不加这个系统会出现很大的异常
    memset(et6416, 0, sizeof(ET6416_data));

    et6416->dev = &client->dev;
    et6416->addr = client->addr;
    et6416->name = DEVICE_NAME;
    et6416->gc.base = -1;
    et6416->client = client;
    et6416->str_name = gpio_desc_name;
    mutex_init(&et6416->i2c_lock);
    mutex_init(&et6416->request_gpio_lock);

    dev_set_drvdata(&client->dev, et6416);

    et6416->et6416_regmap = devm_regmap_init_i2c(client, &et6416_config);
    if (IS_ERR(et6416->et6416_regmap)) {
        et6416_err(et6416->dev, "Failed to initialize regmap\n");
        goto free_memory;
    }

    ret = et6416_get_of_pdata(et6416->dev, et6416);
    if (ret) {
        et6416_err(et6416->dev, "get of pdata fail ret = %d\n", ret);
        goto free_memory;
    }

    et6416_gpiochip_init_set(et6416);

    ret = et6416_hw_init(et6416);
    if (ret) {
        et6416_err(et6416->dev, "hw init fail ret = %d\n", ret);
        goto free_memory;
    }

    ret = devm_gpiochip_add_data(et6416->dev, &et6416->gc.chip, et6416); 
    if (ret) {
        et6416_err(et6416->dev, "Failed to add GPIO chip\n");
        goto free_memory;
    }
#if ET6416_ENABLE_IRQ
    ret = et6416_interrupt_register(et6416);
    if (ret) {
        et6416_err(et6416->dev, "irq register fail ret = %d\n", ret);
        goto free_memory;
    }
#endif
#if ET6416_ENABLE_DEBUGFS
    et6416_create_debugfs(et6416);
#endif
    et6416_err(et6416->dev, "et6416 probe successful\n");
    return 0;

free_memory:
    et6416_err(et6416->dev, "et6416 probe fail\n");
    kfree(et6416);

    return ret;
}

#if KERNEL_VERSION_OVER_6_0_1
static void et6416_i2c_remove(struct i2c_client *client)
#else
static int et6416_i2c_remove(struct i2c_client *client)
#endif
{
#if ET6416_ENABLE_IRQ
    ET6416_data *et6416 = dev_get_drvdata(&client->dev);

    kthread_stop(et6416->et6416_thread);
#endif
    printk(KERN_INFO "I2C device removed: %s\n", client->name);

#if !KERNEL_VERSION_OVER_6_0_1
    return 0;
#endif
}

static const struct i2c_device_id et6416_i2c_id[] = {
    { DEVICE_NAME, 16 },
    { }
};
MODULE_DEVICE_TABLE(i2c, et6416_i2c_id);

static const struct of_device_id et6416_of_match[] = {
    { .compatible = "etek,et6416", },
    { }
};

static struct i2c_driver et6416_i2c_driver = {
    .driver = {
        .name = DEVICE_NAME,
        .owner = THIS_MODULE,
        .of_match_table = et6416_of_match,
    },
    .probe = et6416_i2c_probe,
    .remove = et6416_i2c_remove,
    .id_table = et6416_i2c_id,
};

static int __init et6416_i2c_init(void)
{
    int ret;

    ret = i2c_add_driver(&et6416_i2c_driver);
    if (ret)
        printk(KERN_ERR "Failed to register I2C driver\n");

    return ret;
}

static void __exit et6416_i2c_exit(void)
{
    i2c_del_driver(&et6416_i2c_driver);
}

subsys_initcall(et6416_i2c_init);
module_exit(et6416_i2c_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("hanh@etek.com.cn");
MODULE_DESCRIPTION("Et6416 Device Driver");